import type {AxiosInstance, AxiosResponse, InternalAxiosRequestConfig} from 'axios'
import axios, {type ResponseType} from 'axios'
import NProgress from 'nprogress'
// 在构建时，CSS导入可能会导致问题，改为在使用组件的应用中导入
// import 'nprogress/nprogress.css'
import {$message} from "../tools/feedback.ts";
import type {UIFeedbackTypes} from "../types/ui.types.ts";
import {SYSTEM_KEY, useMorghulisAuthorize} from "./authorize.ts";
import { inject } from "vue";
import type { MorghulisOptions } from "../types/channel.types";

const {check, logout, $client, user, bearer} = useMorghulisAuthorize()


export function useMorghulisRequest(baseURL: string = '/api/', responseType?: ResponseType) {
    function getRequest(auth?: boolean) {
        const instance = axios.create({baseURL, responseType})
        return wrap(instance, auth)
    }
    
    function getMinioRequest(minioURL: string = '/dfs/') {
        const instance = axios.create({baseURL: minioURL, responseType: 'arraybuffer'})
        return wrap(instance)
    }

    function all() {
        // 实现批量请求功能
    }

    return {getRequest, getMinioRequest, all}
}

function wrap(instance: AxiosInstance, auth?: boolean) {
    const {request, response} = instance.interceptors
    request.use((config) => beforeRequest(config, auth), onReject)
    response.use(beforeResponse, onReject)
    return instance
}

function beforeRequest(
    config: InternalAxiosRequestConfig, auth?: boolean
): InternalAxiosRequestConfig | Promise<any> {
    NProgress.start()
    config.headers[SYSTEM_KEY.CLIENT] = $client
    config.headers[SYSTEM_KEY.USER] = user()
    config.headers[SYSTEM_KEY.AUTH] = bearer()
    return config
}


function beforeResponse(
    response: AxiosResponse
): AxiosResponse | Promise<any> {
    NProgress.done()
    let {headers, data} = response
    const UID = headers[SYSTEM_KEY.USER]
    if (UID && !check(UID)) {
        logout()
        return Promise.reject('登录已过期')
    }
    if (data && data.code !== undefined) {
        const {code, message, result} = data
        if (code === 200) return result
        const type = getTypeByCode(code)
        $message[type](message)
        return Promise.reject(message)
    }
    return data
}

function onReject(error: any) {
    NProgress.done()
    if (error.response) {
        const {status} = error.response
        if (status === 401) {
            logout()
            $message.error('登录已过期')
        } else {
            $message.error(`请求错误: ${status}`)
        }
    } else {
        $message.error(`网络错误: ${error.message}`)
    }
    return Promise.reject(error)
}

function getTypeByCode(code: number): UIFeedbackTypes {
    if (code >= 200 && code < 300) return 'success'
    if (code >= 300 && code < 400) return 'info'
    if (code >= 400 && code < 500) return 'warning'
    return 'error'
}